﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Resources;

namespace APP.HELPER.Utils.Localization
{
    public class ResourceEnumConverter : EnumConverter
    {
        private class LookupTable : Dictionary<string, object>
        {
        }
        private readonly Array _flagValues;
        private readonly bool _isFlagEnum;
        private readonly Dictionary<CultureInfo, ResourceEnumConverter.LookupTable> _lookupTables = new Dictionary<CultureInfo, ResourceEnumConverter.LookupTable>();
        private readonly ResourceManager _resourceManager;
        public ResourceEnumConverter(Type type, ResourceManager resourceManager)
            : base(type)
        {
            this._resourceManager = resourceManager;
            object[] customAttributes = type.GetCustomAttributes(typeof(FlagsAttribute), true);
            this._isFlagEnum = (customAttributes.Length > 0);
            if (this._isFlagEnum)
            {
                this._flagValues = Enum.GetValues(type);
            }
        }
        private ResourceEnumConverter.LookupTable GetLookupTable(CultureInfo culture)
        {
            ResourceEnumConverter.LookupTable lookupTable = null;
            if (culture == null)
            {
                culture = CultureInfo.CurrentCulture;
            }
            if (!this._lookupTables.TryGetValue(culture, out lookupTable))
            {
                lookupTable = new ResourceEnumConverter.LookupTable();
                foreach (object current in base.GetStandardValues())
                {
                    string valueText = this.GetValueText(culture, current);
                    if (valueText != null)
                    {
                        lookupTable.Add(valueText, current);
                    }
                }
                this._lookupTables.Add(culture, lookupTable);
            }
            return lookupTable;
        }
        private string GetValueText(CultureInfo culture, object value)
        {
            Type type = value.GetType();
            string text = string.Format("{0}_{1}", type.Name, value);
            string text2 = this._resourceManager.GetString(text, culture);
            if (text2 == null)
            {
                text2 = text;
            }
            return text2;
        }
        private bool IsSingleBitValue(ulong value)
        {
            bool result;
            if (value <= 1uL)
            {
                if (value >= 0uL)
                {
                    switch ((int)value)
                    {
                        case 0:
                            result = false;
                            return result;
                        case 1:
                            result = true;
                            return result;
                    }
                }
            }
            result = ((value & value - 1uL) == 0uL);
            return result;
        }
        private string GetFlagValueText(CultureInfo culture, object value)
        {
            string result;
            if (Enum.IsDefined(value.GetType(), value))
            {
                result = this.GetValueText(culture, value);
            }
            else
            {
                ulong num = (ulong)Convert.ToUInt32(value);
                string text = null;
                foreach (object current in this._flagValues)
                {
                    ulong num2 = (ulong)Convert.ToUInt32(current);
                    if (this.IsSingleBitValue(num2))
                    {
                        if ((num2 & num) == num2)
                        {
                            string valueText = this.GetValueText(culture, current);
                            if (text == null)
                            {
                                text = valueText;
                            }
                            else
                            {
                                text = string.Format("{0}, {1}", text, valueText);
                            }
                        }
                    }
                }
                result = text;
            }
            return result;
        }
        private object GetValue(CultureInfo culture, string text)
        {
            ResourceEnumConverter.LookupTable lookupTable = this.GetLookupTable(culture);
            object result = null;
            lookupTable.TryGetValue(text, out result);
            return result;
        }
        private object GetFlagValue(CultureInfo culture, string text)
        {
            ResourceEnumConverter.LookupTable lookupTable = this.GetLookupTable(culture);
            string[] array = text.Split(new char[]
			{
				','
			});
            ulong num = 0uL;
            string[] array2 = array;
            object result;
            for (int i = 0; i < array2.Length; i++)
            {
                string text2 = array2[i];
                object value = null;
                string key = text2.Trim();
                if (!lookupTable.TryGetValue(key, out value))
                {
                    result = null;
                    return result;
                }
                num |= (ulong)Convert.ToUInt32(value);
            }
            result = Enum.ToObject(base.EnumType, num);
            return result;
        }
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (culture == null)
            {
                culture = CultureInfo.CurrentCulture;
            }
            object result;
            if (value is string)
            {
                object obj = this._isFlagEnum ? this.GetFlagValue(culture, (string)value) : this.GetValue(culture, (string)value);
                if (obj == null)
                {
                    obj = base.ConvertFrom(context, culture, value);
                }
                result = obj;
            }
            else
            {
                result = base.ConvertFrom(context, culture, value);
            }
            return result;
        }
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (culture == null)
            {
                culture = CultureInfo.CurrentCulture;
            }
            object result;
            if (value != null && destinationType == typeof(string))
            {
                object obj = this._isFlagEnum ? this.GetFlagValueText(culture, value) : this.GetValueText(culture, value);
                result = obj;
            }
            else
            {
                result = base.ConvertTo(context, culture, value, destinationType);
            }
            return result;
        }
        public static string ConvertToString(Enum value)
        {
            TypeConverter converter = TypeDescriptor.GetConverter(value.GetType());
            return converter.ConvertToString(value);
        }
        public static List<KeyValuePair<Enum, string>> GetValues(Type enumType, CultureInfo culture)
        {
            List<KeyValuePair<Enum, string>> list = new List<KeyValuePair<Enum, string>>();
            TypeConverter converter = TypeDescriptor.GetConverter(enumType);
            foreach (Enum @enum in Enum.GetValues(enumType))
            {
                KeyValuePair<Enum, string> item = new KeyValuePair<Enum, string>(@enum, converter.ConvertToString(null, culture, @enum));
                list.Add(item);
            }
            return list;
        }
        public static List<KeyValuePair<Enum, string>> GetValues(Type enumType)
        {
            return ResourceEnumConverter.GetValues(enumType, CultureInfo.CurrentUICulture);
        }
    }
}
